#include "itemeditmodel.h"

#include <QDebug>

ItemEditModel::ItemEditModel(QObject *parent) :
    QAbstractItemModel(parent)
{
}

ItemEditModel::ItemEditModel(Item *item, QObject *parent) :
    QAbstractItemModel(parent)
{
    m_item = item;
}

void ItemEditModel::setItem(Item *item)
{
    beginResetModel();
    m_item = item;
    endResetModel();
}

Item *ItemEditModel::item() const
{
    return m_item;
}

QModelIndex ItemEditModel::index(int row, int column, const QModelIndex &parent) const
{
    if (!hasIndex(row, column, parent)) return QModelIndex();
    if (!parent.isValid())
    {
        return createIndex(row, column, 0); // todo: remove magic number!
    }

    int field = parent.row() + 1;
    return createIndex(row, column, field);
}

QModelIndex ItemEditModel::parent(const QModelIndex &child) const
{
    if (!child.isValid() || !child.internalId()) return QModelIndex();

    int field = child.internalId();

    int row = field - 1;
    return createIndex(row, 0, 0); // todo: remove magic number!
}

int ItemEditModel::rowCount(const QModelIndex &parent) const
{
    if (m_item.isNull()) return 0;

    if (!parent.isValid())
    {
        return m_item->fieldCount();
    }

    if (!parent.internalId())
    {
        int field = parent.row();
        return m_item->options(field).count();
    }

    return 0;
}

int ItemEditModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent)

    return (Field_LAST - Field_FIRST + 1);
}

QVariant ItemEditModel::data(const QModelIndex &index, int role) const
{
    if (m_item.isNull() || !index.isValid()) return QVariant();


    switch (index.column())
    {
    case Field_NAME:
        return nameData(index, role);

    case Field_VALUE:
        return valueData(index, role);

    default:
        break;
    }

    return QVariant();
}

bool ItemEditModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (!index.isValid()) return false;

    if (!index.internalId() && role == Qt::EditRole)
    {
        int field = index.row();
        m_item->setValue(field, value);
        emit dataChanged(index, index);
        return true;
    }

    if (index.internalId() && role == Qt::CheckStateRole)
    {
        int field = index.internalId()-1;
        QString option = nameData(index, Qt::DisplayRole).toString();

        QVariantMap optionValues = m_item->optionValues(field);
        if (!optionValues.contains(option))
        {
            return false;
        }

        if (m_item->editType(field) == MetaItem::EditType_SINGLE)
        {
            // reset all values to false if edit type is single
            foreach (QString key, optionValues.keys())
            {
                optionValues.insert(key, false);
            }
        }

        optionValues[option] = (value.toInt() == Qt::Checked);

        m_item->setValue(field, optionValues);
        emit dataChanged(index.parent(), index);
        return true;
    }

    return false;



}

Qt::ItemFlags ItemEditModel::flags(const QModelIndex &index) const
{
    if (!index.internalId())
    {
        if (hasChildren(index))
        {
            return QAbstractItemModel::flags(index);
        }

        return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
    }


    return QAbstractItemModel::flags(index) | Qt::ItemIsUserCheckable; // | Qt::ItemIsEditable;
}

QModelIndex ItemEditModel::buddy(const QModelIndex &index) const
{
    if (index.column() == Field_VALUE) return QAbstractItemModel::buddy(index);

    return index.sibling(index.row(), Field_VALUE);
}



QVariant ItemEditModel::nameData(const QModelIndex &index, int role) const
{
    if (role != Qt::DisplayRole)
    {
        return QVariant();
    }

    int fieldIndex = index.row();
    if (!index.internalId())
    {
        return m_item->fieldName(fieldIndex);
    }

    fieldIndex = index.internalId() - 1;
    QStringList options = m_item->options(fieldIndex);
    int pos = index.row();
    if (pos < 0 || pos >= options.count())
    {
        return QVariant();
    }

    return options.at(pos);
}

QVariant ItemEditModel::valueData(const QModelIndex &index, int role) const
{
    if (!index.isValid()) return QVariant();
    if (role != Qt::DisplayRole && role != Qt::EditRole && role != Qt::CheckStateRole) return QVariant();


    bool top = !index.internalId();
    int field = index.row();

    if (!top)
    {
        field = index.internalId()-1;
    }

    QVariant value = m_item->value(field);
    if (top && (role == Qt::DisplayRole || role == Qt::EditRole))
    {
        return value;
    }


    if (!top && role == Qt::CheckStateRole)
    {
        QString option = nameData(index, Qt::DisplayRole).toString();
        QVariantMap optionValues = m_item->optionValues(field);

        bool selected = optionValues.value(option).toBool();
        if (selected) return Qt::Checked;

        return Qt::Unchecked;

    }

    return QVariant();
}






